package de.voicegym.voicegym.menu

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.view.GravityCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import com.google.android.material.navigation.NavigationView
import de.voicegym.voicegym.R
import de.voicegym.voicegym.databinding.ActivityNavigationDrawerBinding
import de.voicegym.voicegym.menu.settings.SettingsActivity
import de.voicegym.voicegym.recordActivity.RecordActivity
import de.voicegym.voicegym.recordings.ListRecordingsFragment
import de.voicegym.voicegym.recordings.RecordingLibraryFragment
import de.voicegym.voicegym.util.ISetTextable
import de.voicegym.voicegym.util.SwitchToRecordingViewListener


class NavigationDrawerActivity : AppCompatActivity(),
    NavigationView.OnNavigationItemSelectedListener,
    ListRecordingsFragment.ListInteractionListener,
    SwitchToRecordingViewListener {


    override fun switchToRecordingView() {
        switchToRecordingView(null)
    }

    override fun switchToRecordingView(startWithFileName: String?) {
        val intent = Intent(this, RecordActivity::class.java).apply { }
        if (startWithFileName != null) {
            val argumentsBundle = Bundle()
            argumentsBundle.putString(RecordActivity.AUDIO_FILE, startWithFileName)
            intent.putExtras(argumentsBundle)
        }
        startActivity(intent)
    }


    private fun requestPermission() {

        val permissionAudioResult = ContextCompat.checkSelfPermission(
            this,
            Manifest.permission.RECORD_AUDIO
        )
        val permissionStorageReadResult = ContextCompat.checkSelfPermission(
            this,
            Manifest.permission.READ_EXTERNAL_STORAGE
        )
        val permissioStorageWriteResult = ContextCompat.checkSelfPermission(
            this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
        )

        /**
         * READ and WRITE belong to the same permission group (STORAGE).
         * For now(API 27), giving permission to one, doesn't force user interaction for the other.
         */
        val permissionsToRequest =
            listOf(permissionAudioResult, permissionStorageReadResult, permissioStorageWriteResult)
                .zip(
                    listOf(
                        Manifest.permission.RECORD_AUDIO,
                        Manifest.permission.READ_EXTERNAL_STORAGE,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE
                    )
                )
                .filter { it.first != PackageManager.PERMISSION_GRANTED }
                .map { it.second }


        if (permissionsToRequest.isNotEmpty()) {
            // only show dialog, if permission was denied earlier
            if (ActivityCompat.shouldShowRequestPermissionRationale(
                    this,
                    Manifest.permission.RECORD_AUDIO
                )
            ) {
                AlertDialog.Builder(this)
                    .setTitle(R.string.permission_alert_recordAudioMicrophone_title)
                    .setMessage(R.string.permission_alert_recordAudioMicrophone_text)
                    .setPositiveButton(android.R.string.ok) { _, _ ->
                        ActivityCompat.requestPermissions(
                            this,
                            permissionsToRequest.toTypedArray(),
                            REQUEST_PERMISSIONS
                        )
                    }.create().show()
            } else {
                ActivityCompat.requestPermissions(
                    this,
                    permissionsToRequest.toTypedArray(),
                    REQUEST_PERMISSIONS
                )
            }
        } else {
            // permission already granted
        }
    }

    private lateinit var viewBinding: ActivityNavigationDrawerBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewBinding = ActivityNavigationDrawerBinding.inflate(layoutInflater)
        setContentView(viewBinding.root)

        val toolbar = viewBinding.appbarDrawer.toolbar
        setSupportActionBar(toolbar)
        cView = viewBinding.root
        fManager = supportFragmentManager

        val toggle = ActionBarDrawerToggle(
            this,
            viewBinding.drawerLayout,
            toolbar,
            R.string.navigation_drawer_open,
            R.string.navigation_drawer_close
        )
        viewBinding.drawerLayout.addDrawerListener(toggle)
        toggle.syncState()

        viewBinding.navView.setNavigationItemSelectedListener(this)

        requestPermission()
        // always load recordingsfragment since, if we are adding more fragments we need a better way to launch the spectrogram
        loadRecordingsFragment()
    }

    override fun onBackPressed() {
        if (viewBinding.drawerLayout.isDrawerOpen(GravityCompat.START)) {
            viewBinding.drawerLayout.closeDrawer(GravityCompat.START)
        } else {
            finish()
        }
    }


    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        // Handle navigation view item clicks here.
        when (item.itemId) {
            R.id.nav_instruments -> {
                switchToRecordingView()
            }

            R.id.nav_recordings -> {
                loadRecordingsFragment()
            }

            R.id.nav_settings -> {
                val intent = Intent(this, SettingsActivity::class.java)
                startActivity(intent)
            }
        }

        viewBinding.drawerLayout.closeDrawer(GravityCompat.START)
        return true
    }


    private fun loadRecordingsFragment() {
        loadFragment(RecordingLibraryFragment(), "RECORDINGS")
    }

    override fun startSpectrogram() {
        switchToRecordingView()
    }

    override fun openAudioFileInPlaybackMode(fileName: String) {
        switchToRecordingView(fileName)
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when (requestCode) {
            REQUEST_PERMISSIONS -> {
                if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)
                    Toast.makeText(this, "Permission Granted", Toast.LENGTH_SHORT).show()
                else
                    Toast.makeText(this, "Permission NOT Granted", Toast.LENGTH_SHORT).show()
            }
        }
    }

    fun showInputDialog(initialText: String, listener: ISetTextable) {
        // get prompts.xml view
        val layoutInflater = LayoutInflater.from(this)
        val promptView = layoutInflater.inflate(R.layout.input_dialog, null)
        val alertDialogBuilder = AlertDialog.Builder(this)
        alertDialogBuilder.setView(promptView)

        val editText = promptView.findViewById(R.id.inputDialog_editText) as EditText
        editText.setText(initialText)
        // setup a dialog window
        alertDialogBuilder.setCancelable(false)
            .setPositiveButton("OK") { _, _ -> listener.setText(editText.text.toString()) }
            .setNegativeButton(
                "Cancel"
            ) { dialog, id -> dialog.cancel() }

        // create an alert dialog
        val alert = alertDialogBuilder.create()
        alert.show()
    }


    companion object {
        const val REQUEST_PERMISSIONS = 100

        var cView: View? = null

        var fManager: FragmentManager? = null

        private fun <T : Fragment> loadFragment(fragment: T, TAG: String): T {
            fManager?.let { manager ->
                cView?.post {
                    manager.beginTransaction()
                        .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out)
                        .replace(R.id.content_area, fragment, TAG)
                        .commitAllowingStateLoss()
                }

            }

            return fragment
        }
    }
}
